package com.ingenico.insider.services.impl;

import java.awt.Color;
import java.io.IOException;
import java.io.InputStream;
import java.util.MissingResourceException;
import java.util.PropertyResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.ingenico.insider.util.Constants;

public final class UserPreferencesSupplier {
	private static final Logger _logger = Logger.getLogger(UserPreferencesSupplier.class.getCanonicalName());

	/**
	 * singleton instance
	 */
	private static UserPreferencesSupplier instance;

	/**
	 * Public constant keywords
	 */
	public static final String PREFERENCES_FILE = "user.properties";
	public static final String RGB_KEY = "rgb";
	public static final String RGBA_KEY = "rgba";

	/**
	 * The properties bundle that acess the user properties 
	 */
	private final PropertyResourceBundle preferencesBundle;

	/**
	 * private constructor of final class to prevent external instantiation
	 * @throws IOException 
	 */
	private UserPreferencesSupplier() throws IOException {
		getClass().getClassLoader();
		InputStream ios = ClassLoader.getSystemResourceAsStream(PREFERENCES_FILE);
		if (ios != null) {
			preferencesBundle = new PropertyResourceBundle(ios);
		} else {
			final String message = "User preferences file not found (" + PREFERENCES_FILE + ")";
			preferencesBundle = null;
			_logger.log(Level.SEVERE, message);
			throw new MissingResourceException(message, this.getClass().getCanonicalName(), PREFERENCES_FILE);
		}
	}

	/**
	 * retrieve the singleton instance
	 *
	 * @return the UserPreferencesSupplier singleton
	 */
	public static UserPreferencesSupplier getInstance() {
		if (instance == null) {
			_logger.info(UserPreferencesSupplier.class.getName() + " instance does not exist... Creating instance.");
			try {
				instance = new UserPreferencesSupplier();
			} catch (IOException ioe) {
				_logger.log(Level.SEVERE, "User preferences cannot be loaded", ioe);
			}
		}
		return instance;
	}

    /**
     * Gets a string for the given key from this resource bundle or one of its parents.
     * Calling this method is equivalent to calling
     * <blockquote>
     * <code>(String) {@link #getObject(java.lang.String) getObject}(key)</code>.
     * </blockquote>
     *
     * @param key the key for the desired string
     * @exception NullPointerException if <code>key</code> is <code>null</code>
     * @exception MissingResourceException if no object for the given key can be found
     * @exception ClassCastException if the object found for the given key is not a string
     * @return the string for the given key
     */
	public String getString(String preferenceKey) throws MissingResourceException {
		try {
			final String resourceValue = preferencesBundle.getString(preferenceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.finest("Fetched User Preference : " + preferenceKey + " = \"" + resourceValue + "\"");
			} else {
				_logger.info("Fetched Empty User Preference (" + preferenceKey + ")");
			}
			return resourceValue;
		} catch (MissingResourceException mre) {
			_logger.severe("User Preference Key Missing (" + preferenceKey + ").");
			throw mre;
		}
	}

	public Long getDecimal (String preferenceKey) throws MissingResourceException, NumberFormatException {
		try {
			final String resourceValue = preferencesBundle.getString(preferenceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.finest("Fetched User Preference : " + preferenceKey + " = \"" + resourceValue + "\"");
			} else {
				_logger.info("Fetched Empty User Preference (" + preferenceKey + ")");
			}
			return Long.decode(resourceValue);
		} catch (MissingResourceException mre) {
			_logger.severe("User Preference Key Missing (" + preferenceKey + ").");
			throw mre;
		} catch (NumberFormatException nfe) {
			_logger.severe("User Preference Key Missing (" + preferenceKey + ").");
			throw nfe;
		}
	}
	
	public Double getFloat (String preferenceKey) throws MissingResourceException, NumberFormatException {
		try {
			final String resourceValue = preferencesBundle.getString(preferenceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.finest("Fetched User Preference : " + preferenceKey + " = \"" + resourceValue + "\"");
			} else {
				_logger.info("Fetched Empty User Preference (" + preferenceKey + ")");
			}
			return Double.valueOf(resourceValue);
		} catch (MissingResourceException mre) {
			_logger.severe("User Preference Key Missing (" + preferenceKey + ").");
			throw mre;
		} catch (NumberFormatException nfe) {
			_logger.severe("User Preference Key Missing (" + preferenceKey + ").");
			throw nfe;
		}
	}


	public Color getColor (String key) throws MissingResourceException, NumberFormatException {
		String resourceKey;
		String resourceValue;
		boolean hasAlpha = false;

		resourceKey = key + Constants.SEPARATOR + RGBA_KEY;
		try {
			resourceValue = preferencesBundle.getString(resourceKey);
			hasAlpha = true;
		} catch (MissingResourceException mre) {
			resourceKey = key + Constants.SEPARATOR + RGB_KEY;
			try {
				resourceValue = preferencesBundle.getString(resourceKey);
				hasAlpha = false;
			} catch (MissingResourceException mre2) {
				_logger.severe("User Preference Key Missing (" + resourceKey + ").");
				throw mre2;
			}
		}

		if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
			try {
				return new Color(Long.decode(resourceValue).intValue(), hasAlpha);
			} catch (NumberFormatException nfe) {
				_logger.severe("Wrong User Preference Key Data Format for key \"" + resourceKey + "\".");
				throw nfe;
			}
		} else {
			_logger.info("Fetched Empty User Preference (" + resourceKey + ")");
			return null;
		}
	}
}
